﻿package com.kucooler.fog.view {
	import com.kucooler.fog.core.MvcLocator;
	import com.kucooler.fog.core.Notifier;
	import com.kucooler.fog.core.INotifier;
	import com.kucooler.fog.core.Observer;
	import com.kucooler.fog.core.IObserver;
	import com.kucooler.fog.utils.mvcError;
	import com.kucooler.fog.utils.PaperLogger;	
	import flash.display.Sprite;
	import flash.display.Sprite;
	/**
	 * 視圖定位器
	 * <p>單例類,繼承于 MvcLocator, 實現 IViewLocator 接口
	 * <ul>
	 * <li>保存所有已注册的视图对象引用</li>
	 * <li>通過該類來訪問視圖對象</li>
	 * </ul>
	 * </p>
	 *
	 */	
	public class ViewLocator extends MvcLocator implements IViewLocator {
		static private var m_instance:ViewLocator = null;
		protected var m_main:Sprite;   // 文档类
		protected var m_container : Sprite; //主容器类
		protected var m_notifier:INotifier = Notifier.getInstance();
		
		public function ViewLocator() {
			if (m_instance != null) {
				throw new mvcError(mvcError.SINGLETON_VIEW_MSG, ViewLocator);
			}
		}
		/**
		 * 實例化單類
		 * @return	本類對象
		 */
		static public function getInstance():IViewLocator {
			if (m_instance == null) {
				m_instance = new ViewLocator();
			}
			return m_instance;
		}
		
		/**
		 * 文檔入口,调用此函数传入文档类,或者传入已创建的 Sprite
		 * 如果传入的是 Sprite ,则 传递给 view 的对象默认为Sprite
		 * @param r_main  
		 */
		public function initialize(r_container : Sprite):void {
			//m_main = r_main;
			m_container = r_container;
		}
		
		/**
		 * 取回已注冊的视图實例
		 * @param	viewName Class 		要獲取的视图类
		 * @return 	View    			视图实例
		 */
		public function getView(viewName:Class):* {
			if (!hasExists(viewName)) {
				PaperLogger.getInstance().log(mvcError.VIEW_NOT_FOUND, ViewLocator, viewName);
			}
			return m_weeMap[viewName];
		}
		
		/**
		 * 添加视图
		 * @param	viewName Class		    要添加的视图类
		 * @param	stageInstance String    舞臺上某個對象的名稱,缺省為null,此參數將傳遞個視圖類的構造函數,為null時,則傳遞文檔對象給視圖類	
		 *  
		 */
		public function addView(viewName:Class, stageInstance:* = null):void {
			if (!hasExists(viewName)) {
				var container:Sprite;
				if(stageInstance as Sprite){
					container = stageInstance as Sprite;  
				}else {
					container = getContainer(m_container, stageInstance);  //获取stageInstance对象
				}
				
				var viewInstance:IView = new viewName(container); //实例化视图类
				var oberver:IObserver;
				if (viewInstance.notifications.length > 0) { 
					//获取view所关注的通知
					for (var i:uint = 0; i < viewInstance.notifications.length; i++) {
						oberver = new Observer(viewInstance.onDataChanged, viewInstance); //实例化观察者,传递要回调的函数,与函数的执行域
						/**
						 * 如果当前的 notification 是字符串，则添加到通知列表
						 * 此操作意在过滤掉其他 view 对命令 notification 的侦听
						 */
						if (viewInstance.notifications[i] is String) {
							//将观察者实例添加到通知列表中,当该通知被发出,观察者中的回调函数被执行
							m_notifier.addObserver(viewInstance.notifications[i], oberver); 
						}
					}
				}
				//将视图对象添加到视图列表中,以便视图定位器获取该视图对象
				add(viewName, viewInstance); 
			}else {
				PaperLogger.getInstance().log(mvcError.ADD_VIEW_MSG, ViewLocator, viewName);
			}
			
		}
		
		/**
		 * 移除已經註冊的视图
		 * @param	viewName Class		视图类
		 */
		public function removeView(viewName:Class):void {
			if (hasExists(viewName)) {
				var viewInstance:IView = getView(viewName);
				if (viewInstance) {
					var notifications:Array = viewInstance.notifications;
					//移除该视图里面所有的通知
					for ( var i:Number = 0; i < notifications.length; i++ ) {
						m_notifier.removeObserver(notifications[i], viewInstance);
					}
				}
				retrieve(viewName).destroy();				
				remove(viewName); //从视图列表中移除视图对象引用
			}else {
				PaperLogger.getInstance().log(mvcError.REMOVE_VIEW_MSG, ViewLocator, viewName);
			}
		}
		
		/**
		 * 判断此视图是否已经存在
		 * @param  viewName Class		视图类
		 * @return Boolean：			是否存在
		 */
		public function hasView(viewName:Class):Boolean {
			return hasExists(viewName);
		}
		
		//获取 MC
		protected function getContainer(m_container:Sprite, param:String):Sprite {
			var container:Sprite = m_container;
			if (param == null) {
				return container;  
			}			
						
			var _parent:Object;		
			//判断 container 是否是主文档对象
			if (container.stage == container.parent) {  
				_parent = container; //container为文档对象				
			}else {
				_parent = container.parent; 				
			}
			var _obj:Sprite = _parent.getChildByName(param) as Sprite;
			if (_obj != null) {
				return _obj;
			}			
			//如果对象放置于舞台上
			var reg:RegExp = /[\w]+/ig;
			var temp:Array = param.match(reg);
			if (temp && temp.length > 0) {
				for (var i:uint = 0; i < temp.length; i++) {					
					if (container[temp[i]] == null) {
						throw new mvcError(mvcError.MC_NOT_FOUND, ViewLocator, getFullPath(container) + " 容器内的 " +  temp[i]);
					}else {
						container = container[temp[i]];
					}
				}
			}
			return container;
		}
		
		protected function getFullPath(data:Sprite):String {
			var path:String = data.name;
			while (data.stage && (data.parent != data.stage)) {
				data = data.parent as Sprite;
				path = data.name + "." + path;
			}
			return path;
		}
	}
}
